// &i32        // 一个引用
// &'a i32     // 具有显式生命周期的引用
// &'a mut i32 // 具有显式生命周期的可变引用
#![allow(dead_code)]
#![allow(unused_variables)]

mod elimination;
mod r#static;
mod structx;

#[cfg(test)]
mod const_test {
    // 在通过函数签名指定生命周期参数时，并没有改变传入引用或者返回引用的真实生命周期
    // 而是告诉编译器当不满足此约束条件时，就拒绝编译通过
    #[test]
    fn main() {
        // result 的生命周期必须为 两个参数中生命周期较小的

        let string1 = String::from("long string is long");
        let result: &str = "a";
        {
            let string2 = String::from("xyz");
            // result = longest(string1.as_str(), string2.as_str()); //borrowed value does not live long enough
            // string2  只能活到内部语句块的花括号处

            if false {
                println!("{}", string1);
                println!("{}", string2);
            }
        }

        println!("The longest string is {}", result);
    }

    // 和泛型一样，使用生命周期参数，需要先声明 <'a>
    // x、y 和返回值至少活得和 'a 一样久(因为返回值要么是 x，要么是 y)
    fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
        if x.len() > y.len() { x } else { y }
    }

    // 函数的返回值如果是一个引用类型，那么它的生命周期只会来源于：
    //
    //     函数参数的生命周期
    //     函数体中某个新建引用的生命周期 -->典型的悬垂引用场景

    #[test]
    fn fun_life() {
        // result 的生命周期必须为 两个参数中生命周期较小的

        let string1 = String::from("long string is long");
        let string2 = String::from("xyz");
        longest_own(string1.as_str(), string2.as_str()); //borrowed value does not live long enough
    }

    // // 返回函数内引用-->悬垂指针
    // fn longest_<'a>(x: &str, y: &str) -> &'a str {
    //     let result = String::from("really long string");
    //     result.as_str() // returns a value referencing data owned by the current function
    // }

    // 直接返回所有权
    fn longest_own<'a>(x: &str, y: &str) -> String {
        println!("{} {}", x, y);
        String::from("really long string")
    }
}

#[cfg(test)]
mod struct_life {
    #[derive(Debug)]
    struct ImportantExcerpt<'a> {
        part: &'a str, //结构体 ImportantExcerpt 所引用的字符串 str 必须比该结构体活得更久。
    }

    #[test]
    fn struct_short() {
        let novel = String::from("Call me Ishmael. Some years ago...");
        let first_sentence = novel.split('.').next().expect("Could not find a '.'");
        let i = ImportantExcerpt {
            part: first_sentence,
        };

        println!("{:?}", i.part)
    }

    #[test]
    fn struct_long() {
        let i;
        {
            let novel = String::from("Call me Ishmael. Some years ago...");
            let first_sentence = novel.split('.').next().expect("Could not find a '.'");
            i = ImportantExcerpt {
                part: first_sentence,
            };
            // 可以看出结构体比它引用的字符串活得更久，引用字符串在内部语句块末尾 } 被释放后
            // println! 依然在外面使用了该结构体，因此会导致无效的引用，

            println!("{:?}", i);
        }
        // println!("{:?}", i);
    }
}

#[cfg(test)]
mod example {
    use std::fmt::Display;

    fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
    where
        T: Display,
    {
        println!("Announcement! {}", ann);
        if x.len() > y.len() { x } else { y }
    }

    #[test]
    fn struct_short() {
        longest_with_an_announcement("aa", "bb", "cc");
    }
}
